package com.luo.gmall.gateway.filter;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.List;

/**
 * @author Zoro
 * @date 2021年11月21
 * 局部过滤器
 *
 * 局部过滤器：拦截特定路由的请求
 * 		1.编写一个类XxxGatewayFilterFactory实现GatewayFilterFactory接口 继承AbstractGatewayFilterFactory基类（推荐）
 * 		2.在yml配置中配置过滤器
 * 			filters:
 * 				- Xxx
 * 		如果向过滤器中传递固定数量的参数，需要额外实现一下步骤：
 * 		3.定义静态内部类：KeyValueConfig
 * 		4.继承AbstractGatewayFilterFactory基类时，指定泛型为KeyValueConfig实体类
 * 		5.重写父类的无参构造方法，调用super(KeyValueConfig.class)
 * 		6.重写shortcutFieldOrder方法，返回字段顺序
 * 		如果要接受不定数量的参数。需要额外实现以下步骤：
 * 		7.在实体类中定义集合字段
 * 		8.重写shortcutType方法，返回：ShortcutType.GATHER_LIST
 */
@Component
@Slf4j
public class TestGatewayFilterFactory extends AbstractGatewayFilterFactory<TestGatewayFilterFactory.ListValueConfig> {
    public TestGatewayFilterFactory() {
        super(ListValueConfig.class);
    }

    @Override
    public GatewayFilter apply(ListValueConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                // 固定参数
                /*log.info("局部过过滤器只过滤对应服务的请求,config中的值为：name = " + config.getKey() + ",value = " + config.getValue());*/

                log.info("局部过过滤器只过滤对应服务的请求,config中的值为：values = " + config.values);
                return chain.filter(exchange);
            }
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
//        return Arrays.asList("key", "value");
        return Collections.singletonList("values");
    }

    @Override
    public ShortcutType shortcutType() {
        return ShortcutType.GATHER_LIST;
    }

    @Data
    public static class KeyValueConfig {
        private String key;
        private String value;
    }

    @Data
    public static class ListValueConfig {
        private List<String> values;
    }
}
